<?php

/*
 * 切割合并文件
 * @package
 * @author     wanglei@wyzc.com
 * @version    $Id$
 */

class FileChunk {

	public $file = array();

	private $maxSize;


	public function __construct() {
		ini_set('memory_limit', '-1');
		$this->maxSize = 1024 * 1024 * 50;
	}

	/**
	 * $maxSize 是每次读取文件时占用的内存，默认50M
	 * 它的值越高，切割或合并文件速度越快，但是内存占用也越高
	 * 可以根据机器配置适当调整
	 * @param $size
	 */
	public function sexMaxSize($size) {
		$this->maxSize = $size;
	}

	/**
	 * 切割文件
	 * @param $filePath //文件名
	 * @param $chunkNum //切割块数
	 */
	public function cut($filePath, $chunkNum) {
		$this->init($filePath);
		$chunks  = $this->getChunks($chunkNum);
		$rowFile = fopen($filePath, 'r');
		foreach ($chunks as $chunk) {
			$size      = $chunk['size'];
			$chunkFile = fopen('./' . $chunk['name'], 'w');
			while (!feof($rowFile)) {
				$data = fread($rowFile, $this->getReadSize($size));
				$size -= $this->getReadSize($size);
				fwrite($chunkFile, $data);
				if ($size <= 0) {
					break;
				}
			}
			echo $chunk['name'] . '生成成功,文件大小' . $chunk['size'] . PHP_EOL;
			fclose($chunkFile);
		}
		fclose($rowFile);
	}

	/**
	 * 合并文件
	 * @param array $files
	 * @param       $newFilename
	 */
	public function merge($files = array(), $newFilename) {
		$newFile = fopen($newFilename, 'w');
		foreach ($files as $file) {
			if (!file_exists($file)) die('文件不存在');
			$size      = filesize($file);
			$chunkFile = fopen($file, 'r');
			while (!feof($chunkFile)) {
				$data = fread($chunkFile, $this->getReadSize($size));
				fwrite($newFile, $data);
			}
			echo $file . ' 已合并' . PHP_EOL;
		}
		echo $newFilename . '已经全部合并成功';
	}

	/**
	 * 获取文件基本信息
	 */
	private function init($filePath) {
		$file       = new SplFileInfo($filePath);
		$this->file = array(
			'file_name'  => $file->getFilename(),
			'isFile'     => $file->isFile(),
			'isReadable' => $file->isReadable(),
			'isWritable' => $file->isWritable(),
			'size'       => $file->getSize(),
		);
		if (!$this->file['isFile']) {
			die('不是一个有效的文件');
		}
		if (!$this->file['isReadable'] || !$this->file['isWritable']) {
			die('文件不可读写');
		}
		echo '文件总大小：' . $this->file['size'] . '字节' . PHP_EOL;
	}


	/**
	 * 计算每块文件的大小
	 * @param $chunkNum
	 * @return array
	 */
	private function getChunks($chunkNum) {
		$count = 0;
		while ($this->file['size'] % $chunkNum != 0) {
			$this->file['size']--;
			$count++;
		}
		$chunks = array();
		for ($i = 0; $i < $chunkNum; $i++) {
			$chunks[$i]['name'] = $this->file['file_name'] . '_' . ($i + 1);
			$chunks[$i]['size'] = $this->file['size'] / $chunkNum;
		}

		$chunks[$chunkNum - 1]['size'] += $count;
		return $chunks;
	}


	/**
	 * 计算每次读取的文件大小
	 * @param $size
	 * @return int
	 */
	private function getReadSize($size) {
		if ($size < $this->maxSize) return $size;
		return $this->maxSize;
	}

}

$obj = new FileChunk();
$obj->sexMaxSize(200 * 1024 * 1024);
$obj->cut('./hadoop.mp4', 5);
//$obj->merge([
//	'./hadoop.mp4_1',
//	'./hadoop.mp4_2',
//	'./hadoop.mp4_3',
//	'./hadoop.mp4_4',
//	'./hadoop.mp4_5',
//], './newhadoop.mp4');
